package ss.pku.jsa.type.inference;

import ss.pku.jsa.type.constraint.solver.QError;

public class FieldPropogationJob implements ConstraintJob {
	ObjectQType parent;
	RefQType field;

	public FieldPropogationJob(ObjectQType parent, RefQType field) {
		this.parent = parent;
		this.field = field;
		if (JqualPlugin.showContraintMsgs)
			JqualPlugin.out.println("Adding " + this);
	}

	public String toString() {
		return "Field Prop: " + this.parent + " " + this.field;
	}

	public void apply() {
		for (Constraint c : this.parent.getConstraints()) {
			boolean fromParent = c.from.equals(this.parent);

			ObjectQType other = null;
			if (fromParent)
				other = c.to;
			else {
				other = c.from;
			}

			RefQType otherField = other.lookupFieldQType(this.field.getKey(),
					this.field.isStatic);
			if (otherField == null) {
				if ((other instanceof ClassQType)) {
					continue;
				}

				if (!JqualPlugin.analysis.isLegalField(other.getType(),
						this.field.getKey())) {
					continue;
				}

				Profile.logMemStart("FieldPropogationJob.apply()/RefQType.copy()");
				otherField = this.field.copy(c.loc);
				Profile.logMemEnd();
				otherField.setKey(this.field.getKey());
				other.addFieldQType(this.field.getKey(), otherField);
			}

			if (fromParent) {
				Constraint
						.addConstraint(this.field, otherField, c.qgate, c.loc,
								c.polarity, QError.FIELDPROP,
								Constraint.Kind.LT);
			} else
				Constraint
						.addConstraint(otherField, this.field, c.qgate, c.loc,
								c.polarity, QError.FIELDPROP,
								Constraint.Kind.LT);
		}
	}
}
